package com.yituo.mjworld.mvc.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.yituo.mjworld.core.utils.Constant;
import com.yituo.mjworld.core.utils.OtherTool;
import com.yituo.mjworld.core.web.core.BaseForm;
import com.yituo.mjworld.core.web.core.Result;
import com.yituo.mjworld.mvc.dao.UserDao;
import com.yituo.mjworld.mvc.dao.WxUserDao;
import com.yituo.mjworld.mvc.entity.UserData;
import com.yituo.mjworld.mvc.entity.other.UserAccount;
import com.yituo.mjworld.mvc.entity.web.*;
import com.yituo.mjworld.mvc.form.DeleteForm;
import com.yituo.mjworld.mvc.form.QueryForm;
import com.yituo.mjworld.mvc.form.support.user.Login;
import com.yituo.mjworld.mvc.form.support.user.QueryUser;
import com.yituo.mjworld.mvc.service.BaseService;
import org.iherus.codegen.qrcode.SimpleQrcodeGenerator;
import org.junit.jupiter.api.Test;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.io.IOException;
import java.lang.reflect.Field;
import java.math.BigDecimal;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

/**
 * @author xq
 */
@Service
public class UserServiceImpl extends BaseService {

  @Autowired
  UserDao userDao;
  @Autowired
  WxUserDao wxUserDao;
  @Autowired
  QiniuServiceImpl qiniuService;

  public static void main(String[] args) throws IOException {
    System.out.println(new WxServiceImpl().getWxConfig("asjahsdjghghbajsdhajhasjkdhnak", "http://www.baidu.com"));
  }

  /**
   * 查找推荐人
   */
  public WebUser getReferrer(String userId) {
    return (WebUser) baseDao.get(WebUser.class, userId);
  }

  /**
   * 获取账户信息情况
   */
  public UserAccount getAccountInfo(WebUser user) {
    UserAccount account = (UserAccount) this.baseDao.get(UserAccount.class, user.getId());
    if (account == null) {
      account = new UserAccount();
      account.setRealMoney(BigDecimal.ZERO);
      account.setRestMoney(BigDecimal.ZERO);
      account.setRestMoney(BigDecimal.ZERO);
    }
    return account;
  }

  /**
   * 通过手机号码
   *
   * @return
   */
  public WebUser bindUserForMobile(String ref, String mobile) {
    // 1.检查user
    WebUser user = userDao.getUserByMobile(mobile);
    if (user == null) {
      // 新用户
      user = new WebUser();
      user.setReferrer(ref);
      user.setRule(UserRole.WEB_USER);
      user.setScale(1);
      user.setRegisterDate(new Date());
      user.setId(OtherTool.getUUID());
      user.setAccount(mobile);
      user.setPassword("*");
      user.setNickname(mobile);
    } else {
      user.setLastLoginDate(new Date());
    }
    this.baseDao.saveOrUpdate(user);
    return user;
  }

  /**
   * 获取用户通过手机号码
   *
   * @return
   */
  public WebUser getUserByPhone(String mobile) {
    return this.userDao.getUserByMobile(mobile);
  }

  /**
   * 获取用户通过userId
   *
   * @return
   */
  public WebUser getUserByUserId(String userId) {
    return (WebUser) this.baseDao.get(WebUser.class, userId);
  }

  /**
   * 手机号码是否已经存在!
   *
   * @return
   */
  public boolean mobileIsExits(String mobile) {
    WebUser webUser = this.userDao.getUserByMobile(mobile);
    if (webUser == null) {
      return false;
    }
    return true;
  }

  /**
   * 获取指定ID的用户
   *
   * @param userId
   * @return
   */
  public WebUser getUser(String userId) {
    return (WebUser) userDao.get(WebUser.class, userId);
  }

  /**
   * 获取用户清单
   *
   * @param form 查询语句
   * @return
   */
  @Override
  public JSONObject getList(QueryForm form) {
    QueryUser queryForm = (QueryUser) form;
    String sql = "select " +
        " a.id," +
        " a.account," +
        " a.nickname," +
        " a.wxId," +
        " a.headImage," +
        " a.telphone," +
        " a.email," +
        " a.registerDate," +
        " a.lastLoginDate," +
        " a.rule," +
        " a.scale," +
        " a.referrer," +
        " b.openid " +
        " from web_user a left join wx_userinfo b on a.id=b.userId " +
        " where a.rule!=" + UserRole.SUPER_ADMIN + " and a.registerDate>:startDate and a.registerDate<:endDate ";
    String countSql = "select count(a.id) from web_user a where  a.rule!=" + UserRole.SUPER_ADMIN + " and a.registerDate>:startDate and a.registerDate<:endDate ";
    String where = "";
    queryForm.getParam().clear();
    if (queryForm.queryType == QueryUser.QUERY_BY_ID) {
      where = " and  a.id=:userId ";
      form.getParam().put("userId", queryForm.getKey());
    } else if (queryForm.queryType == QueryUser.QUERY_BY_NICKNAME) {
      if (!StringUtils.isEmpty(queryForm.getKey())) {
        where = " and a.nickname like '%" + queryForm.getKey() + "%' ";
      }
    }
    form.getParam().put("startDate", queryForm.startDate);
    form.getParam().put("endDate", queryForm.endDate);
    String order = " order by a.registerDate desc ";
    if (queryForm.asc) {
      order = " order by a.registerDate asc ";
    }
    sql = sql + where + order;
    countSql = countSql + where;
    return get(sql, countSql, queryForm, queryForm.getParam());
  }

  /**
   * 管理员可操作!
   * 欲删除的用户为代理用户的话.
   *
   * @param id
   * @return
   */
  @Override
  public Result delete(DeleteForm id) {
    return null;
  }

  /**
   * 保存或者更新
   *
   * @param baseForm
   * @return
   */
  @Override
  public Result saveOrUpdate(BaseForm baseForm) {
    WebUser user = (WebUser) baseForm;
    baseDao.saveOrUpdate(user);
    return new Result().setResult(true).setMsg(user.getId());
  }

  /**
   * 更新密码
   *
   * @param userId      欲更新的帐号
   * @param newPassword 新的密码
   * @return
   */
  public boolean updatePassword(String userId, String newPassword) {
    WebUser user = (WebUser) this.userDao.get(WebUser.class, userId);
    if (user == null) {
      return false;
    }
    user.setPassword(newPassword);
    baseDao.saveOrUpdate(newPassword);
    return true;
  }

  /**
   * 登录
   *
   * @return
   */
  public WebUser login(Login form) {
    return userDao.login(form.account, form.password);
  }


  /**
   * 获取我的二维码
   *
   * @param currentUser
   * @return
   */
  public String getMyQrCode(WebUser currentUser) {
    if (currentUser == null) {
      return null;
    }
    WebUserQrcode vo = (WebUserQrcode) this.baseDao.get(WebUserQrcode.class, currentUser.getId());
    if (vo != null) {
      return vo.getQrCode();
    }
    return null;
  }

  /**
   * 获取用户二维码
   *
   * @param userId 用户ID
   * @return 生成成功返回该用户的二维码地址, 生成失败"";
   */
  public String getUserQrcode(String userId) {
    if (StringUtils.isEmpty(userId)) {
      return null;
    }
    WebUserQrcode qrcodeVo = (WebUserQrcode) this.baseDao.get(WebUserQrcode.class, userId);
    if (qrcodeVo != null) {
      return qrcodeVo.getQrCode();
    }
    // 3.生成用户用于推广的连接
    String url = "";
    if (Constant.IS_DEV) {
      url = Constant.DOMAIN_DEV + "qr?k=" + userId;
    } else {
      url = Constant.DOMAIN_PRO + "qr?k=" + userId;
    }
    System.out.println(url);
    // 4.生成对应的二维码URL以及图片
    String qrCodeUrl = "C:\\image\\mjserver\\qrcode\\" + userId + ".png";
    try {
      new SimpleQrcodeGenerator().generate(url).toFile(qrCodeUrl);
      // 二维码上传七牛
      String qiniuUrl = qiniuService.uploadQrcode(qrCodeUrl);
      return qiniuUrl;
    } catch (IOException e) {
      // 二维码生成失败!
      e.printStackTrace();
      return "";
    }
  }

  /**
   * 获取用户申请到的二维码信息记录
   *
   * @param userId
   * @return
   */
  public WebUserQrcode getUserQrCodeInfo(String userId) {
    return userDao.getUserQrCodeInfo(userId);
  }

  /**
   * 获取指定用户的订单
   *
   * @param form
   */
  public JSONObject getUserOrders(QueryForm form, String userId) {
    String sql = "select " +
        " orderId," +
        " goodsId," +
        " goodsName," +
        " buyNum," +
        " buyPrice," +
        " createDate," +
        " orderStatus, " +
        " payDate," +
        " userId," +
        " userNote," +
        " transportId " +
        " from web_order " +
        " where userId=:userId";
    String countSql = "select count(orderId) from web_order where userId=:userId";
    Map<String, Object> params = new HashMap<String, Object>(1);
    params.put("userId", userId);
    return get(sql, countSql, form, params);
  }


  /**
   * 从数据库中获取到用户的信息
   *
   * @param userId
   * @return
   */
  public WxUserinfo getWxUserInfo(String userId) {
    return this.userDao.getWxUserInfoByUserId(userId);
  }

  /**
   * 保存信息
   *
   * @param wxUserinfo
   */
  public void saveOrUpdate(WxUserinfo wxUserinfo) {
    this.baseDao.saveOrUpdate(wxUserinfo);
  }

  /**
   * 获取到完整的用户信息
   *
   * @param user
   * @return
   */
  public JSONObject getUserInfo(WebUser user) {
    JSONObject result = new JSONObject();
    JSONObject info = (JSONObject) JSONObject.toJSON(user);
    // 移除用户的密码
    info.remove("password");
    // 是否通过实名认证
    info.put("isValidatePass", userDao.isValidatePass(user.getId()));
    // 用户的信息
    result.put("userInfo", info);
    WxUserinfo wxInfo = userDao.getWxUserInfoByUserId(user.getId());
    // 微信的信息
    result.put("wxInfo", wxInfo);
    // 用户金币的帐号情况
    result.put("userAccountInfo", getAccountInfo(user));
    return result;
  }

  /**
   * 绑定用户
   * <p>
   * 这类用户扫描了用户的推广二维码.
   *
   * @return
   */
  public String bindUser(String reffer, WxUserinfo wxUserInfo) {
    WxUserinfo wxUserInfoFromDb = wxUserDao.getWxUserByOpenId(wxUserInfo.getOpenid());
    String userId;
    if (wxUserInfoFromDb != null) {
      // 该用户已经是本站的微信类扫码用户了
      userId = wxUserInfoFromDb.getUserId();
      WebUser webUser = (WebUser) this.baseDao.get(WebUser.class, userId);
      // 更新用户登录日期
      webUser.setLastLoginDate(new Date());
      // 更新用户头像
      webUser.setHeadImage(wxUserInfo.getHeadimgurl());
      // 更新用户昵称
      webUser.setNickname(wxUserInfo.getNickname());
      baseDao.update(webUser);
      // 更新数据库中的微信信息
      wxUserInfo.setUserId(wxUserInfoFromDb.getUserId());
      baseDao.merge(wxUserInfo);
    } else {
      userId = OtherTool.getUUID();
      WebUser user = new WebUser();
      user.setId(userId);
      user.setAccount(wxUserInfo.getOpenid());
      user.setPassword("*");
      user.setNickname(wxUserInfo.getNickname());
      user.setRegisterDate(new Date());
      user.setReferrer(reffer);
      user.setScale(1);
      user.setLastLoginDate(new Date());
      // 默认的权限为游客
      user.setRule(UserRole.WEB_USER);

      // 静默创建一个游客帐号.
      this.baseDao.saveOrUpdate(user);

      // 游离态存入缓存
      WebUser target = new WebUser();
      BeanUtils.copyProperties(user, target);
      UserData.getUserMap().put(target.getId(), target);

      // 绑定微信
      wxUserInfo.setUserId(userId);

      this.baseDao.saveOrUpdate(wxUserInfo);
    }
    return userId;
  }

  /**
   * 信息补齐接口
   *
   * @param userId
   * @param filedName
   * @param value
   */
  public Result setMyInfo(String userId, String filedName, String value) {
    Result result = null;
    UserInfoRecord record = (UserInfoRecord) this.baseDao.get(UserInfoRecord.class, userId);
    if (record == null) {
      record = new UserInfoRecord();
      record.setUserId(userId);
      result = setObjectValue(record, filedName, value);
      if (result.getResult()) {
        this.baseDao.save(record);
      }
      return result;
    } else {
      result = getObjectValue(record, filedName);
      String oldImage = (String) result.getMsg();
      result = setObjectValue(record, filedName, value);
      if (result.getResult()) {
        this.baseDao.update(record);
        if (OtherTool.fileIsExist(UserData.getUploadPath()+ oldImage)) {
          // 删除之前上传的文件
          System.out.println(OtherTool.deleteFile(UserData.getUploadPath()+ oldImage));
        }
      }
      return result;
    }
  }


  /**
   * 设置某个对象指定字段的值
   *
   * @param obj
   * @param fieldName
   * @param value
   * @return
   */
  private Result setObjectValue(Object obj, String fieldName, Object value) {
    Result result = new Result().setResult(false);
    Class clazz = obj.getClass();
    try {
      Field field = clazz.getDeclaredField(fieldName);
      field.setAccessible(true);
      field.set(obj, value);
    } catch (NoSuchFieldException e) {
      return result.setMsg("字段不存在!");
    } catch (IllegalAccessException e) {
      e.printStackTrace();
      return result.setMsg("访问了私有字段!");
    }
    return result.setResult(true);
  }

  /**
   * 设置某个对象指定字段的值
   *
   * @param obj
   * @param fieldName
   * @return
   */
  private Result getObjectValue(Object obj, String fieldName) {
    Result result = new Result().setResult(false);
    Class clazz = obj.getClass();
    try {
      Field field = clazz.getDeclaredField(fieldName);
      field.setAccessible(true);
      return result.setMsg(field.get(obj));
    } catch (NoSuchFieldException e) {
      return result.setMsg("字段不存在!");
    } catch (IllegalAccessException e) {
      e.printStackTrace();
      return result.setMsg("访问了私有字段!");
    }
  }


  @Test
  public void test() {
    System.out.println(setObjectValue(new UserInfoRecord(), "userId", "111"));
  }
}
